// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
//
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
// copy, modify, and distribute this software in source code or binary form for use
// in connection with the web services and APIs provided by Facebook.
//
// As with any software that integrates with the Facebook platform, your use of
// this software is subject to the Facebook Developer Principles and Policies
// [http://developers.facebook.com/policy/]. This copyright notice shall be
// included in all copies or substantial portions of the software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#import "TargetConditionals.h"

#if !TARGET_OS_TV

 #import "FBSDKAppLinkReturnToRefererView.h"

 #import "FBSDKAppLink.h"
 #import "FBSDKAppLinkTarget.h"
 #import "FBSDKCoreKitBasicsImport.h"
 #import "FBSDKInternalUtility.h"

 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-implementations"

static const CGFloat FBSDKMarginX = 8.5f;
static const CGFloat FBSDKMarginY = 8.5f;

static NSString *const FBSDKRefererAppLink = @"referer_app_link";
static NSString *const FBSDKRefererAppName = @"app_name";
static NSString *const FBSDKRefererUrl = @"url";
static const CGFloat FBSDKCloseButtonWidth = 12.0;
static const CGFloat FBSDKCloseButtonHeight = 12.0;

@interface FBSDKAppLinkReturnToRefererView ()

@property (nonatomic, strong) UILabel *labelView;
@property (nonatomic, strong) UIButton *closeButton;
@property (nonatomic, strong) UITapGestureRecognizer *insideTapGestureRecognizer;

@end

@implementation FBSDKAppLinkReturnToRefererView
{
  BOOL _explicitlyHidden;
}

 #pragma mark - Initialization

- (instancetype)initWithFrame:(CGRect)frame
{
  self = [super initWithFrame:frame];
  if (self) {
    [self commonInit];
    [self sizeToFit];
  }
  return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
  self = [super initWithCoder:aDecoder];
  if (self) {
    [self commonInit];
  }
  return self;
}

- (void)commonInit
{
  // Initialization code
  _includeStatusBarInSize = FBSDKIncludeStatusBarInSizeAlways;

  // iOS 7 system blue color
  self.backgroundColor = [UIColor colorWithRed:0.0f green:122.0f / 255.0f blue:1.0f alpha:1.0f];
  self.textColor = [UIColor whiteColor];
  self.clipsToBounds = YES;

  [self initViews];
}

- (void)initViews
{
  if (!_labelView && !_closeButton) {
    _closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
    _closeButton.backgroundColor = [UIColor clearColor];
    _closeButton.userInteractionEnabled = YES;
    _closeButton.clipsToBounds = YES;
    _closeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
    _closeButton.contentMode = UIViewContentModeCenter;
    [_closeButton addTarget:self action:@selector(closeButtonTapped:) forControlEvents:UIControlEventTouchUpInside];

    [self addSubview:_closeButton];

    _labelView = [[UILabel alloc] initWithFrame:CGRectZero];
    _labelView.font = [UIFont systemFontOfSize:[UIFont smallSystemFontSize]];
    _labelView.textColor = [UIColor whiteColor];
    _labelView.backgroundColor = [UIColor clearColor];
    _labelView.textAlignment = NSTextAlignmentCenter;
    _labelView.clipsToBounds = YES;
    [self updateLabelText];
    [self addSubview:_labelView];

    _insideTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapInside:)];
    _labelView.userInteractionEnabled = YES;
    [_labelView addGestureRecognizer:_insideTapGestureRecognizer];

    [self updateColors];
  }
}

 #pragma mark - Layout

- (CGSize)intrinsicContentSize
{
  CGSize size = self.bounds.size;
  if (_closed || !self.hasRefererData) {
    size.height = 0.0;
  } else {
    CGSize labelSize = [_labelView sizeThatFits:size];
    size = CGSizeMake(size.width, labelSize.height + 2 * FBSDKMarginY + self.statusBarHeight);
  }
  return size;
}

- (void)layoutSubviews
{
  [super layoutSubviews];

  CGRect bounds = self.bounds;

  _labelView.preferredMaxLayoutWidth = _labelView.bounds.size.width;
  CGSize labelSize = [_labelView sizeThatFits:bounds.size];
  _labelView.frame = CGRectMake(
    FBSDKMarginX,
    CGRectGetMaxY(bounds) - labelSize.height - 1.5f * FBSDKMarginY,
    CGRectGetMaxX(bounds) - FBSDKCloseButtonWidth - 3 * FBSDKMarginX,
    labelSize.height + FBSDKMarginY
  );

  _closeButton.frame = CGRectMake(
    CGRectGetMaxX(bounds) - FBSDKCloseButtonWidth - 2 * FBSDKMarginX,
    _labelView.center.y - FBSDKCloseButtonHeight / 2.0f - FBSDKMarginY,
    FBSDKCloseButtonWidth + 2 * FBSDKMarginX,
    FBSDKCloseButtonHeight + 2 * FBSDKMarginY
  );
}

- (CGSize)sizeThatFits:(CGSize)size
{
  if (_closed || !self.hasRefererData) {
    size = CGSizeMake(size.width, 0.0);
  } else {
    CGSize labelSize = [_labelView sizeThatFits:size];
    size = CGSizeMake(size.width, labelSize.height + 2 * FBSDKMarginY + self.statusBarHeight);
  }
  return size;
}

 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (CGFloat)statusBarHeight
{
  UIApplication *application = [UIApplication sharedApplication];

  BOOL include;
  switch (_includeStatusBarInSize) {
    case FBSDKIncludeStatusBarInSizeAlways:
      include = YES;
      break;
    case FBSDKIncludeStatusBarInSizeNever:
      include = NO;
      break;
  }
  if (include && !application.statusBarHidden) {
    BOOL landscape = UIInterfaceOrientationIsLandscape(FBSDKInternalUtility.statusBarOrientation);
    CGRect statusBarFrame = application.statusBarFrame;
    return landscape ? CGRectGetWidth(statusBarFrame) : CGRectGetHeight(statusBarFrame);
  }

  return 0;
}

 #pragma clang diagnostic pop

 #pragma mark - Public API

- (void)setIncludeStatusBarInSize:(FBSDKIncludeStatusBarInSize)includeStatusBarInSize
{
  _includeStatusBarInSize = includeStatusBarInSize;
  [self setNeedsLayout];
  [self invalidateIntrinsicContentSize];
}

- (void)setTextColor:(UIColor *)textColor
{
  _textColor = textColor;
  [self updateColors];
}

- (void)setRefererAppLink:(FBSDKAppLink *)refererAppLink
{
  _refererAppLink = refererAppLink;
  [self updateLabelText];
  [self updateHidden];
  [self invalidateIntrinsicContentSize];
}

- (void)setClosed:(BOOL)closed
{
  if (_closed != closed) {
    _closed = closed;
    [self updateHidden];
    [self invalidateIntrinsicContentSize];
  }
}

- (void)setHidden:(BOOL)hidden
{
  _explicitlyHidden = hidden;
  [self updateHidden];
}

 #pragma mark - Private

- (void)updateLabelText
{
  NSString *appName = (_refererAppLink && [FBSDKTypeUtility array:_refererAppLink.targets objectAtIndex:0]) ? [[FBSDKTypeUtility array:_refererAppLink.targets objectAtIndex:0] appName] : nil;
  _labelView.text = [self localizedLabelForReferer:appName];
}

- (void)updateColors
{
  UIImage *closeButtonImage = [self drawCloseButtonImageWithColor:_textColor];

  _labelView.textColor = _textColor;
  [_closeButton setImage:closeButtonImage forState:UIControlStateNormal];
}

- (UIImage *)drawCloseButtonImageWithColor:(UIColor *)color
{
  UIGraphicsBeginImageContextWithOptions(CGSizeMake(FBSDKCloseButtonWidth, FBSDKCloseButtonHeight), NO, 0.0f);

  CGContextRef context = UIGraphicsGetCurrentContext();

  CGContextSetStrokeColorWithColor(context, color.CGColor);
  CGContextSetFillColorWithColor(context, color.CGColor);

  CGContextSetLineWidth(context, 1.25f);

  CGFloat inset = 0.5f;

  CGContextMoveToPoint(context, inset, inset);
  CGContextAddLineToPoint(context, FBSDKCloseButtonWidth - inset, FBSDKCloseButtonHeight - inset);
  CGContextStrokePath(context);

  CGContextMoveToPoint(context, FBSDKCloseButtonWidth - inset, inset);
  CGContextAddLineToPoint(context, inset, FBSDKCloseButtonHeight - inset);
  CGContextStrokePath(context);

  UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  return result;
}

- (NSString *)localizedLabelForReferer:(NSString *)refererName
{
  if (!refererName) {
    return nil;
  }

  NSString *format = NSLocalizedString(@"Touch to return to %1$@", @"Format for the string to return to a calling app.");
  return [NSString stringWithFormat:format, refererName];
}

- (BOOL)hasRefererData
{
  return _refererAppLink && [FBSDKTypeUtility array:_refererAppLink.targets objectAtIndex:0];
}

- (void)closeButtonTapped:(id)sender
{
  [_delegate returnToRefererViewDidTapInsideCloseButton:self];
}

- (void)onTapInside:(UIGestureRecognizer *)sender
{
  [_delegate returnToRefererViewDidTapInsideLink:self link:_refererAppLink];
}

- (void)updateHidden
{
  super.hidden = _explicitlyHidden || _closed || !self.hasRefererData;
}

@end

 #pragma clang diagnostic pop
#endif
